
 

import UIKit

fileprivate enum NavLayoutConstants {
    static let margin: CGFloat = 5
    static let defaultLeftMargin: CGFloat = 10
    static let defaultRightMargin: CGFloat = 15
    static let defaultButtonWidth: CGFloat = 36
    static let defaultStackHeight: CGFloat = 36
    static let defaultAlpha: CGFloat = 0.2
}

class BarButton: UIButton {
    
    
}

// MARK: - BarItem
class BarItem {
    let view: UIView
    
    var size: CGSize {
        get {view.bounds.size}
        set {
            view.bounds.size = newValue
        }
    }
    
    required init(view: UIView) {
        self.view = view
     }
    
    static func itemWithImage(_ image: UIImage?, target: Any?, action: Selector?, size: CGSize = CGSize(width: NavLayoutConstants.defaultButtonWidth, height: NavLayoutConstants.defaultStackHeight)) -> BarItem {
        let button = BarButton()
        button.setImage(image, for: .normal)
//        button.setImage(image, for: .highlighted)
        button.bounds.size = size
        if let target = target, let action = action {
            button.addTarget(target, action: action, for: .touchUpInside)
        }
        return self.init(view: button)
    }
    
    static func itemWithTitle(_ title: String?, color: UIColor?, font: UIFont, target: Any? = nil, action: Selector? = nil, size: CGSize? = nil) -> BarItem {
        let button = BarButton(type: .system)
        button.setTitleColor(color, for: .normal)
        button.setTitleColor(color, for: .highlighted)
        button.titleLabel?.lineBreakMode = .byTruncatingTail
        button.setTitle(title, for: .normal)
        button.titleLabel?.font = font
        
        if let buttonSize = size {
            button.bounds.size = buttonSize
        } else {
            if title != nil {
                button.bounds.size = CGSizeMake(calculateTextSize(text: title!, font: font, maxWidth: screenWidth * 0.3).width, NavLayoutConstants.defaultStackHeight)
            }
        }
        
        if let target = target, let action = action {
            button.addTarget(target, action: action, for: .touchUpInside)
        }
        return self.init(view: button)
    }
    
    // 通过自定义 UIView 创建 BarItem
    static func itemWithView(_ customView: UIView) -> BarItem {
        return self.init(view: customView)
    }
}

// MARK: - BackItem (保持不变，但基于 BarItem)
class BackItem: BarItem {
    func setWhiteColor() {
        let backButton = self.view as? UIButton
        backButton?.setImage(UIImage(named: "icon_back_white"), for: .normal)
    }
    
    func setBlackColor() {
        let backButton = self.view as? UIButton
        backButton?.setImage(UIImage(named: "nav_back"), for: .normal)
    }
}

// MARK: - GradientImageView (无需修改)
class GradientImageView: UIImageView {
    var gradientColors: [UIColor]? {
        didSet {
            updateGradient()
        }
    }
    
    override class var layerClass: AnyClass {
        return CAGradientLayer.self
    }
    
    private var gradientLayer: CAGradientLayer {
        return layer as! CAGradientLayer
    }
    
    func setStartPoint(_ startPoint: CGPoint, endPoint: CGPoint) {
        gradientLayer.startPoint = startPoint
        gradientLayer.endPoint = endPoint
    }
    
    private func updateGradient() {
        guard let colors = gradientColors else {
            gradientLayer.colors = nil
            return
        }
        gradientLayer.colors = colors.map { $0.cgColor }
        setStartPoint(CGPoint(x: 0, y: 0), endPoint: CGPoint(x: 1, y: 0))
    }
}

// MARK: - BarStackView
class BarStackView: UIView {

    var spacing: Int = 0 {
        didSet {
            setNeedsLayout()
        }
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        
        for (index, subview) in subviews.enumerated() {
            var x: CGFloat = 0
            if index > 0 {
                let previousView = subviews[index - 1]
                x = previousView.frame.maxX + CGFloat(spacing)
            }
            
            // 使用 subview 的固有大小，如果没有设置则使用默认值
            let width = subview.frame.width > 0 ? subview.frame.width : NavLayoutConstants.defaultButtonWidth
            let height = subview.frame.height > 0 ? subview.frame.height : NavLayoutConstants.defaultStackHeight
            
            subview.frame = CGRect(
                x: x,
                y: (bounds.height - height) / 2,
                width: width,
                height: height
            )
        }
    }
    
    // 添加 BarItem 的 view
    func addBarItem(_ barItem: BarItem) {
        addSubview(barItem.view)
    }
    
    var dynamicWidth: CGFloat {
        var totalWidth = subviews.reduce(0) { $0 + $1.frame.width }
        if subviews.count > 1 {
            totalWidth = totalWidth + CGFloat(spacing * (subviews.count - 1))
        }
        return totalWidth
    }
}

// MARK: - NavigationBar
class NavigationBar: UIView {
    
    var hasStatusBar: Bool = true {
        didSet {
            layoutView()
        }
    }
    var leftOffetX: CGFloat = 0.0
    var rightOffetX: CGFloat = 0.0

    // MARK: Properties
    var leftBarItem: BarItem? {
        didSet {
            if let item = leftBarItem {
                leftBarItems = [item]
            }
        }
    }
    
    var rightBarItem: BarItem? {
        didSet {
            if let item = rightBarItem {
                rightBarItems = [item]
            } else {
                rightBarButtonsStackView.subviews.forEach { $0.removeFromSuperview() }
            }
        }
    }
    
    var leftBarItems: [BarItem] = [] {
        didSet {
            updateLeftBarItems()
        }
    }
    
    var rightBarItems: [BarItem] = [] {
        didSet {
            updateRightBarItems()
        }
    }
    
    var titleView: UIView? {
        didSet {
            updateTitleView()
        }
    }
    
    var rightBarView: UIView? {
        didSet {
            updateRightBarView()
        }
    }
    
    var titleTextColor: UIColor? {
        didSet {
            titleLabel.textColor = titleTextColor
        }
    }
    
    var titleTextAttributes: [NSAttributedString.Key: Any]? {
        didSet {
            updateTitleAttributes()
        }
    }
    
    var backgroundImage: UIImage? {
        didSet {
            backgroundView.image = backgroundImage
            backgroundView.backgroundColor = nil
        }
    }
    
    var barTintColor: UIColor? {
        didSet {
            backgroundView.backgroundColor = barTintColor
            backgroundView.image = nil
        }
    }
    
    private(set) var lineView: UIView = {
        let view = UIView()
        view.backgroundColor = UIColor(red: 245/255, green: 245/255, blue: 245/255, alpha: 1)
        view.isHidden = true
        return view
    }()
    
    private(set) lazy var backBarItem: BackItem? = {
        let backItems = leftBarItems.compactMap { $0 as? BackItem }
        return backItems.first
    }()
    
    private(set) lazy var contentView: UIView = navigationBarContentView
    
    var gradientColors: [UIColor]? {
        didSet {
            backgroundView.gradientColors = gradientColors
        }
    }
    
    var isBackButtonHidden: Bool = false {
        didSet {
            leftBarButtonsStackView.isHidden = isBackButtonHidden
        }
    }
    
    var isTitleHidden: Bool = false {
        didSet {
            titleLabel.isHidden = isTitleHidden
        }
    }
    
    var title: String? {
        didSet {
            updateTitle()
        }
    }
    
    // MARK: Private Properties
    private lazy var navigationBarContentView: UIView = {
        let view = UIView()
        return view
    }()
    
    private lazy var backgroundView: GradientImageView = {
        let view = GradientImageView(frame: bounds)
        view.isUserInteractionEnabled = true
        view.backgroundColor = .white
        return view
    }()
    
    private(set) lazy var leftBarButtonsStackView: BarStackView = {
        let stack = BarStackView()
        navigationBarContentView.addSubview(stack)
        return stack
    }()
    
    private(set) lazy var rightBarButtonsStackView: BarStackView = {
        let stack = BarStackView()
        stack.spacing = 6
        navigationBarContentView.addSubview(stack)
        return stack
    }()
    
    private lazy var titleLabel: UILabel = {
        let label = UILabel()
        label.textAlignment = .center
        label.textColor = UIColor(red: 51/255, green: 51/255, blue: 51/255, alpha: 1)
        label.font = .systemFont(ofSize: 17, weight: .medium)
        navigationBarContentView.addSubview(label)
        return label
    }()
    
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupViews()
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private func setupViews() {
        addSubview(backgroundView)
        addSubview(navigationBarContentView)
        addSubview(lineView)
    }
    
    func layoutView() {
        
        backgroundView.frame = bounds

        if hasStatusBar {
            navigationBarContentView.frame = CGRect(x: 0, y: Int(statusBarHeight), width: Int(width), height: Int(height) - Int(statusBarHeight))
        } else {
            navigationBarContentView.frame = CGRect(x: 0, y: 0, width: Int(width), height: Int(height))
        }
        
        lineView.frame = CGRect(x: 0, y: height - 0.5, width: UIScreen.main.bounds.width, height: 0.5)
            
        if let titleView = titleView {
            titleView.frame = CGRect(
                x: (width - titleView.width) / 2,
                y: (navigationBarContentView.height - titleView.height) / 2,
                width: titleView.width,
                height: titleView.height
            )
        }
        
        if let title = title, !isTitleHidden {
            titleLabel.text = title
            titleLabel.sizeToFit()
            titleLabel.width = min(250, titleLabel.width)
            titleLabel.frame = CGRect(
                x: (width - titleLabel.width) / 2,
                y: (navigationBarContentView.height - titleLabel.height) / 2,
                width: titleLabel.width,
                height: titleLabel.height
            )
        }
        
        leftBarButtonsStackView.frame = CGRect(x: NavLayoutConstants.defaultLeftMargin + leftOffetX, y: 2, width: leftBarButtonsStackView.dynamicWidth, height: navigationBarContentView.height - 4)
        
        let rightStackViewTotalWidth = rightBarButtonsStackView.dynamicWidth
        rightBarButtonsStackView.frame = CGRect(x: screenWidth - (NavLayoutConstants.defaultRightMargin + rightOffetX) - rightStackViewTotalWidth, y: 2, width: rightStackViewTotalWidth, height: navigationBarContentView.height - 4)
 
    }
    
    
    
    // MARK: Layout
    override func layoutSubviews() {
        super.layoutSubviews()
                
        layoutView()
    }
    
    // MARK: Public Methods
    func setStartPoint(_ startPoint: CGPoint, endPoint: CGPoint) {
        backgroundView.setStartPoint(startPoint, endPoint: endPoint)
    }

    // MARK: Private Methods
    private func resizeBarItem(_ barItem: BarItem) {
        let view = barItem.view
        var size: CGSize = .zero
        if view.frame.width > 0, view.frame.height > 0 {
            size = CGSize(
                width: min(view.frame.width, UIScreen.main.bounds.width / 2),
                height: view.backgroundColor != nil ? min(view.frame.height, NavLayoutConstants.defaultStackHeight) : NavLayoutConstants.defaultStackHeight
            )
        } else {
            view.sizeToFit()
            size = CGSize(width: min(ceil(UIScreen.main.bounds.width / 2), max(view.frame.width, NavLayoutConstants.defaultButtonWidth)), height: NavLayoutConstants.defaultStackHeight)
        }
        view.frame.size = size
    }
    
    private func updateLeftBarItems() {
        leftBarButtonsStackView.subviews.forEach { $0.removeFromSuperview() }
        leftBarItems.forEach {
            resizeBarItem($0)
            leftBarButtonsStackView.addBarItem($0)
        }
        layoutView()
    }
    
    private func updateRightBarItems() {
        rightBarButtonsStackView.subviews.forEach { $0.removeFromSuperview() }
        rightBarItems.forEach {
            rightBarButtonsStackView.addBarItem($0)
            resizeBarItem($0)
        }
        layoutView()
    }
    
    private func updateTitleView() {
        titleLabel.removeFromSuperview()
        guard let titleView = titleView else { return }
        navigationBarContentView.addSubview(titleView)
        layoutView()
    }
    
    private func updateRightBarView() {
        rightBarButtonsStackView.subviews.forEach { $0.removeFromSuperview() }
        guard let rightBarView = rightBarView else { return }
        rightBarButtonsStackView.addSubview(rightBarView)
        rightBarView.frame.size = CGSize(width: rightBarView.bounds.width, height: 36)

        layoutView()

    }
    
    private func updateTitle() {
        guard !isTitleHidden else { return }
        if (title == nil) {
            isTitleHidden = true
            titleLabel.removeFromSuperview()
        } else {
            titleLabel.text = title
        }
        layoutView()
    }
    
    private func updateTitleAttributes() {
        guard let attributes = titleTextAttributes, let text = titleLabel.text else { return }
        titleLabel.attributedText = NSAttributedString(string: text, attributes: attributes)
    }
    
    override var backgroundColor: UIColor? {
        didSet {
            backgroundView.image = nil
            backgroundView.backgroundColor = backgroundColor
        }
    }
    
    override var alpha: CGFloat {
        didSet {
            backgroundView.alpha = alpha
            lineView.isHidden = alpha < 1
        }
    }
}

 
